﻿using System.Collections.Generic;

namespace QueryBuilder.Core.Query.Type
{
    /// <summary>
    /// 
    /// </summary>
    public abstract class TypeMappingsRegistry
    {
        private IDictionary<string, ITypeMapping> typeByTypeOfName = new Dictionary<string, ITypeMapping>();

        /// <summary>
        /// Initializes a new instance of the <see cref="TypeMappingsRegistry"/> class.
        /// </summary>
        protected TypeMappingsRegistry()
        {
            this.RegisterTypeMappings();
        }

        /// <summary>
        /// Gets the type mapping.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public ITypeMapping GetTypeMapping(string name)
        {
            ITypeMapping typeMapping = this.Basic(name);
            return typeMapping;
        }

        /// <summary>
        /// Registers the type mapping.
        /// </summary>
        /// <param name="typeMapping">The type mapping.</param>
        /// <param name="additionalName">Name of the additional.</param>
        protected void RegisterTypeMapping(ITypeMapping typeMapping, string additionalName)
        {
            this.typeByTypeOfName[typeMapping.ReturnedClass.FullName] = typeMapping;
            this.typeByTypeOfName[typeMapping.ReturnedClass.AssemblyQualifiedName] = typeMapping;
            this.typeByTypeOfName[typeMapping.Name] = typeMapping;

            if (additionalName != null)
            {
                this.typeByTypeOfName[additionalName] = typeMapping;
            }
        }

        /// <summary>
        /// Registers the type mappings.
        /// </summary>
        protected abstract void RegisterTypeMappings();

        /// <summary>
        /// Basics the specified name.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        protected virtual ITypeMapping Basic(string name)
        {
            if (this.typeByTypeOfName.ContainsKey(name))
            {
                ITypeMapping typeMapping = this.typeByTypeOfName[name];
                if (typeMapping != null)
                {
                    return typeMapping;
                }
            }

            return null;
        }
    }
}